/*
 * @Author: Jiraiya
 * @Date: 2020-03-12 12:01:49
 * @LastEditors: Jiraiya
 * @LastEditTime: 2020-03-16 16:35:04
 * @Description: 
 */

// 执行 tsc检查编译

//🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏
// 泛型
function id<T>(x: T): T{
    return x;
}

const val = id('123')


function sum(arr:Array<number>): Promise<number>{
    const sum = arr.reduce((total, val) => total + val, 0);
    return Promise.resolve(sum);
}
sum([1, 2, 3]).then(res => { console.log(res) })

//🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏
//泛型实现链表
class CommentList<T>{
    value: T;

    next?:CommentList<T>;
    
    constructor(value: T, next?: CommentList<T>){
        this.value = value;
        this.next = next;
    }

    setNext(next: CommentList<T>){
        this.next = next;
        return next;
    }

    grow(value: T){
        const t = new CommentList(value);
        this.setNext(t);
        return t;
    }

    toString():string{
        return this.next ? 
        JSON.stringify(this.value) + ' -> ' + this.next.toString():
        JSON.stringify(this.value) + ' -> null';
    }
}

const c = new CommentList(1);
c.grow(2).grow(3).grow(4);
console.log(c.toString());
// 1 -> 2 -> 3 -> 4 -> null

//🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏
// 交叉与联合
// 构造类型 & 满足两种 交叉类型
type User = {
    id: number;
    name: string;
}
type Blog = {
    id: number;
    content: string;
    title: string;
}
type UserWithHisBlogs = User & {
    blogs: Array<Blog>;
}

type Single = [number, string]
type Arr = [Single, Single]
const n:Arr = [[1, '1'], [1, '1']]

// | 满足一种即可 联合类型
type Suffix = '先生' | '女士';
const sayName = (name:string, suffix:Suffix):string => {
    return name + ' ' + suffix;
}
sayName('王', '先生')

//🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏
//never是any的对立面 跟谁都不相等 除了自己
let ne:never;
// ne = null

//🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏
// extends 继承类型
interface User1 {
    permission: number;
    name: string
}

interface AdminUser extends User1{
    permission: 100
}

const obj:AdminUser = {
    permission: 100,
    name: 'ww',
}


// 约束泛型
interface HasName{
    name:string;
}
function sayObjName<T extends HasName>(obj: T):void{
    console.log(obj.name)
}
sayObjName({name: 'ww'})

// 构造对象索引 键为字符串
interface UserInfo{
    name: string;
    age: number;
}
interface MapObj{
    [uid:string]: UserInfo;
}
const map1:MapObj = {
    a: {name:'ww', age: 2}
}

//🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏
// 键名联合 keyof 返回对象key的一个联合类型

interface Person{
    name: string;
    age: number;
    sex: 0 | 1;
}
type KeyOfPerson = keyof Person;
const personKey:KeyOfPerson = 'sex';



type ObjToNum<T> = {
    [key in keyof T]: number
}
type Person1 = {
    name: string;
    address: string;
}
type test = ObjToNum<Person1>;
const m:test = {
    name: 1,
    address: 2
}

// 类型赋值
type P1 = {
    name: any,
    address: any,
    sayName: any,
}
type P2<T extends P1> = {
    [key in keyof P1]: T[key]
}
type P3 = P2<{
    name: string,
    address: string,
    sayName: () => void,
    xx: number
}>

const pp:P3 = {
    name: '1',
    address: '2',
    sayName(){}
}

//🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏
//构造条件类型
//剔除掉ABC中的函数
type ABC = {a:1, b():string, c(): number, d: 'x'}
type AnyFunc = (...args:Array<unknown>) => unknown //符合该条件即为函数
const obj1:ABC = {
    a:1,
    b(){return 'x'},
    c(){return 1},
    d: 'x'
}

type Test1 = {
    [k in keyof ABC]: (ABC[k] extends AnyFunc ? never : k)
}

type Test2 = Test1[keyof ABC]

type Test3 = {
    [k in Test2]: ABC[k]
}

//获取对象中的非函数类型
type GetUnFuncInObj<T> = {
    [k in keyof T]: T[k] extends AnyFunc ? never : k
}[keyof T]

type GetUnFunc<T> = {
    [k in GetUnFuncInObj<T>]:T[k]
}
interface Obj2{
    a:string,
    b(): number,
    c: boolean
}
type Result = GetUnFunc<Obj2>
const obj3:Result = {
    a: 'x',
    c: true
}

//🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏
//使用infer进行extends推断
type PromiseVal<P> = P extends Promise<infer INNER> ? INNER : P;
type PStr = PromiseVal<string>

type ArrayVal<P> = P extends Array<infer INNER> ? INNER : P;

// Test ==> string | number
type Test = ArrayVal<[string, number]>;